home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / uupc11yt.zip / RNEWS / EXPIRE.C next >
C/C++ Source or Header  |  1993-04-05  |  20KB  |  538 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    e x p i r e . c                                                 */
  3. /*                                                                    */
  4. /*    Expire old news articles for UUPC/extended                      */
  5. /*                                                                    */
  6. /*    Copyright (c) 1992-1993 by Kendra Electronic Wonderworks, all   */
  7. /*    rights reserved except those explicitly granted by the UUPC/    */
  8. /*    extended license.                                               */
  9. /*--------------------------------------------------------------------*/
  10.  
  11. /*
  12.  *    $Id: EXPIRE.C 1.4 1993/04/05 04:32:19 ahd Exp $
  13.  *
  14.  *    $Log: EXPIRE.C $
  15.  * Revision 1.4  1993/04/05  04:32:19  ahd
  16.  * Add timestamp, size to information returned by directory searches
  17.  *
  18.  * Revision 1.3  1992/11/25  12:59:17  ahd
  19.  * Modifiy summery messages
  20.  *
  21.  */
  22.  
  23. /*--------------------------------------------------------------------*/
  24. /*                        System include files                        */
  25. /*--------------------------------------------------------------------*/
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <ctype.h>
  31. #include <time.h>
  32. #include <limits.h>
  33.  
  34. /*--------------------------------------------------------------------*/
  35. /*                    UUPC/extended include files                     */
  36. /*--------------------------------------------------------------------*/
  37.  
  38. #include "lib.h"
  39. #include "active.h"
  40. #include "dater.h"
  41. #include "getopt.h"
  42. #include "hlib.h"
  43. #include "import.h"
  44. #include "importng.h"
  45. #include "logger.h"
  46. #include "uundir.h"
  47. #include "pushpop.h"
  48. #include "stater.h"
  49. #include "timestmp.h"
  50.  
  51. currentfile();
  52.  
  53. /*--------------------------------------------------------------------*/
  54. /*                          Global Variables                          */
  55. /*--------------------------------------------------------------------*/
  56.  
  57. #define ONE_DAY (60L*60L*24L)
  58.  
  59. /*--------------------------------------------------------------------*/
  60. /*                        Internal prototypes                         */
  61. /*--------------------------------------------------------------------*/
  62.  
  63. static boolean numeric( char *start);
  64.  
  65. static void ExpireAll( const time_t expire_date,
  66.                        const time_t archive_date );
  67.  
  68. static void  ExpireGroup( const char *group,
  69.                       const time_t expire_date,
  70.                       const time_t archive_date );
  71.  
  72. static void ExpireOneGroup( struct grp *cur_grp,
  73.                       const time_t expire_date,
  74.                       const time_t archive_date );
  75.  
  76. static void ExpireDirectory( struct grp *cur_grp,
  77.                       const time_t expire_date,
  78.                       const char *directory,
  79.                       const char *archive );
  80.  
  81. static boolean numeric( char *start);
  82.  
  83. static void usage( void );
  84.  
  85. long total_articles_purged   = 0;
  86. long total_articles_archived = 0;
  87. long total_articles_kept     = 0;
  88. long total_bytes_purged   = 0;
  89. long total_bytes_archived = 0;
  90. long total_bytes_kept     = 0;
  91.  
  92. /*--------------------------------------------------------------------*/
  93. /*    m a i n                                                         */
  94. /*                                                                    */
  95. /*    Main program                                                    */
  96. /*--------------------------------------------------------------------*/
  97.  
  98. void main( int argc, char **argv)
  99. {
  100.    int c;
  101.    extern char *optarg;
  102.    extern int   optind;
  103.    char *group = NULL;
  104.  
  105.    time_t expire_period  = 7; /* Seven days visible to users         */
  106.    time_t archive_period = 0; /* Seven days after expiring in arch   */
  107.  
  108.    time_t expire_date;
  109.    time_t archive_date;
  110.  
  111. /*--------------------------------------------------------------------*/
  112. /*     Report our version number and date/time compiled               */
  113. /*--------------------------------------------------------------------*/
  114.  
  115.    debuglevel = 1;
  116.    banner( argv );
  117.  
  118. #if defined(__CORE__)
  119.    copywrong = strdup(copyright);
  120.    checkref(copywrong);
  121. #endif
  122.  
  123. /*--------------------------------------------------------------------*/
  124. /*        Process our arguments                                       */
  125. /*--------------------------------------------------------------------*/
  126.  
  127.    while ((c = getopt(argc, argv, "e:a:g:x:n:")) !=  EOF)
  128.       switch(c) {
  129.  
  130.       case 'a':
  131.          archive_period = atoi( optarg );
  132.          break;
  133.  
  134.       case 'e':
  135.          expire_period = atoi( optarg );
  136.          break;
  137.  
  138.       case 'n':
  139.          group = optarg;
  140.          break;
  141.  
  142.       case 'x':
  143.          debuglevel = atoi( optarg );
  144.          break;
  145.  
  146.       case '?':
  147.          usage();
  148.          exit(1);
  149.          break;
  150.  
  151.       default:
  152.          printmsg(0, "expire - invalid option -%c", c);
  153.          usage();
  154.          exit(2);
  155.          break;
  156.    }
  157.  
  158.    if (optind != argc) {
  159.       fputs("Extra parameter(s) at end.\n", stderr);
  160.       usage();
  161.       exit(2);
  162.    }
  163.  
  164. /*--------------------------------------------------------------------*/
  165. /*                             Initialize                             */
  166. /*--------------------------------------------------------------------*/
  167.  
  168.    tzset();                      /* Set up time zone information  */
  169.  
  170.    if (!configure( B_NEWS ))
  171.       exit(1);   /* system configuration failed */
  172.  
  173. /*--------------------------------------------------------------------*/
  174. /*                  Switch to the spooling directory                  */
  175. /*--------------------------------------------------------------------*/
  176.  
  177.    PushDir( E_newsdir );
  178.    atexit( PopDir );
  179.  
  180. /*--------------------------------------------------------------------*/
  181. /*                     Initialize logging file                        */
  182. /*--------------------------------------------------------------------*/
  183.  
  184.    openlog( NULL );
  185.  
  186. /*--------------------------------------------------------------------*/
  187. /*                       Load the active file                         */
  188. /*--------------------------------------------------------------------*/
  189.  
  190.    get_active();              /* Get sequence numbers for groups from
  191.                                  active file                      */
  192.  
  193. /*--------------------------------------------------------------------*/
  194. /*                  Compute times for expiring files                  */
  195. /*--------------------------------------------------------------------*/
  196.  
  197.    time( &expire_date );
  198.    expire_date  -= (expire_period * ONE_DAY);
  199.    archive_date = expire_date - (archive_period * ONE_DAY);
  200.  
  201.    printmsg(1,"%s: %sing news older than %s (%ld days)",
  202.             argv[0],
  203.             archive_period ?  "Archiv" : "Purg",
  204.             dater( expire_date , NULL), (long) expire_period );
  205.  
  206.    if ( archive_period != 0 )
  207.       printmsg(1,"%s: Purging news older than %s",
  208.             argv[0],
  209.                   dater( archive_date , NULL));
  210.  
  211. /*--------------------------------------------------------------------*/
  212. /*    Process one group if requested, otherwise process the entire    */
  213. /*    active file                                                     */
  214. /*--------------------------------------------------------------------*/
  215.  
  216.       if ( group != NULL )
  217.          ExpireGroup( group, expire_date, archive_date );
  218.       else
  219.          ExpireAll(expire_date, archive_date );
  220.  
  221. /*--------------------------------------------------------------------*/
  222. /*                         Clean up and exit                          */
  223. /*--------------------------------------------------------------------*/
  224.  
  225.    put_active();
  226.  
  227.    if ( total_articles_purged || total_articles_archived)
  228.       printmsg(1,"%s: Purged %ld total articles (%ld bytes), "
  229.                     "archived %ld total articles (%ld bytes). " ,
  230.                   argv[0],
  231.                   total_articles_purged,   total_bytes_purged,
  232.                   total_articles_archived, total_bytes_archived );
  233.  
  234.    printmsg(1,"%s: Left alone %ld articles (%ld bytes).  "
  235.                  "Total of %ld articles now use %ld bytes." ,
  236.                argv[0],
  237.                total_articles_kept,     total_bytes_kept,
  238.                total_articles_kept + total_articles_archived,
  239.                total_bytes_kept + total_bytes_archived );
  240.  
  241.    exit(0);
  242.  
  243. } /* main */
  244.  
  245. /*--------------------------------------------------------------------*/
  246. /*    E x p i r e A l l                                               */
  247. /*                                                                    */
  248. /*    Expire all defined news groups                                  */
  249. /*--------------------------------------------------------------------*/
  250.  
  251. static void ExpireAll( const time_t expire_date,
  252.                 const time_t archive_date )
  253. {
  254.    struct grp *cur_grp = group_list;
  255.  
  256.    while ( cur_grp != NULL )
  257.    {
  258.       ExpireOneGroup( cur_grp, expire_date, archive_date );
  259.                                     /* Clean up this group           */
  260.  
  261.       cur_grp = cur_grp->grp_next;  /* Then clean up the next group  */
  262.    }
  263. } /* Expire_All */
  264.  
  265. /*--------------------------------------------------------------------*/
  266. /*    E x p i r e G r o u p                                           */
  267. /*                                                                    */
  268. /*    Clean up one group by name                                      */
  269. /*--------------------------------------------------------------------*/
  270.  
  271. static void  ExpireGroup( const char *group,
  272.                       const time_t expire_date,
  273.                       const time_t archive_date )
  274. {
  275.    struct grp *cur_grp = group_list;
  276.    struct grp *target = NULL;
  277.  
  278. /*--------------------------------------------------------------------*/
  279. /*         Search the list of groups for the requested group          */
  280. /*--------------------------------------------------------------------*/
  281.  
  282.    while ( (cur_grp != NULL) && (target == NULL))
  283.    {
  284.       if ( equal( cur_grp->grp_name, group ))
  285.          target = cur_grp;
  286.  
  287.       cur_grp = cur_grp->grp_next;  /* Then clean up the next group  */
  288.    }
  289.  
  290. /*--------------------------------------------------------------------*/
  291. /*   If we found the group, process it, otherwise report the error    */
  292. /*--------------------------------------------------------------------*/
  293.  
  294.    if ( target == NULL )
  295.       printmsg(0,"Unable to locate active group %s", group );
  296.    else
  297.       ExpireOneGroup( target, expire_date, archive_date );
  298.                                     /* Clean up this group           */
  299.  
  300. } /* ExpireGroup */
  301.  
  302. /*--------------------------------------------------------------------*/
  303. /*    E x p i r e O n e G r o u p                                     */
  304. /*                                                                    */
  305. /*    Clean up one group by name                                      */
  306. /*--------------------------------------------------------------------*/
  307.  
  308. static void ExpireOneGroup( struct grp *cur_grp,
  309.                       const time_t expire_date,
  310.                       const time_t archive_date )
  311. {
  312.    char groupdir[FILENAME_MAX];
  313.    char archdir[FILENAME_MAX];
  314.  
  315.    printmsg(3,"Processing news group %s", cur_grp->grp_name );
  316.  
  317. /*--------------------------------------------------------------------*/
  318. /*                     Set up the directory names                     */
  319. /*--------------------------------------------------------------------*/
  320.  
  321.    ImportNewsGroup( groupdir, cur_grp->grp_name, 0 );
  322.    mkfilename( archdir, E_archivedir, &groupdir[ strlen( E_newsdir) + 1] );
  323.  
  324. /*--------------------------------------------------------------------*/
  325. /*            Process the primary and archive directories             */
  326. /*--------------------------------------------------------------------*/
  327.  
  328.    ExpireDirectory( cur_grp, archive_date, archdir, NULL);
  329.                               /* Purge archive first to keep
  330.                                  directory smaller                   */
  331.  
  332.    ExpireDirectory( cur_grp, expire_date, groupdir,
  333.                     (archive_date < expire_date) ? archdir : NULL);
  334.                               /* Do not archive for 0 days!          */
  335.  
  336. } /* ExpireOneGroup */
  337.  
  338. /*--------------------------------------------------------------------*/
  339. /*    E x p i r e D i r e c t o r y                                   */
  340. /*                                                                    */
  341. /*    Clean up one group by name                                      */
  342. /*--------------------------------------------------------------------*/
  343.  
  344. static void ExpireDirectory( struct grp *cur_grp,
  345.                       const time_t expire,
  346.                       const char *directory,
  347.                       const char *archive )
  348. {
  349.    char fname[FILENAME_MAX];
  350.  
  351.    int articles_archived = 0;/* Count of files moved to archive        */
  352.    int articles_purged   = 0;/* Count of files actually deleted        */
  353.    int articles_kept     = 0;/* Count of files actually deleted        */
  354.    long bytes_purged = 0;    /* Bytes freed on disk from deletions     */
  355.    long bytes_kept   = 0;    /* Bytes left on disk total               */
  356.    long bytes_archived = 0;  /* Bytes left on disk in archive          */
  357.  
  358.    boolean not_built = TRUE;  /* Did not insure archive directory
  359.                                  exists                           */
  360.  
  361.    long low = LONG_MAX;  /* Oldest article number left             */
  362.  
  363.    DIR *dirp;
  364.    struct direct *dp;
  365.  
  366. /*--------------------------------------------------------------------*/
  367. /*                Open up the directory for processing                */
  368. /*--------------------------------------------------------------------*/
  369.  
  370.    if ((dirp = opendirx(directory,"*.*")) == nil(DIR))
  371.    {
  372.       printmsg(3, "ExpireDirectory: couldn't opendir() %s", directory);
  373.       cur_grp->grp_low = cur_grp->grp_high;
  374.       return;
  375.    } /* if */
  376.  
  377. /*--------------------------------------------------------------------*/
  378. /*                 Switch to directory for processing                 */
  379. /*--------------------------------------------------------------------*/
  380.  
  381.    CHDIR( directory );
  382.  
  383. /*--------------------------------------------------------------------*/
  384. /*              Look for the next file in the directory               */
  385. /*--------------------------------------------------------------------*/
  386.  
  387.    while((dp = readdir(dirp)) != nil(struct direct))
  388.    {
  389.  
  390. /*--------------------------------------------------------------------*/
  391. /*                      Archive/expire this file?                     */
  392. /*--------------------------------------------------------------------*/
  393.  
  394.       if ( numeric( dp->d_name ))/* Article format name?             */
  395.       {                          /* Yes --> Examine it closer        */
  396.  
  397.          printmsg(6,"Processing file %s from %s",
  398.                   dp->d_name, dater( dp->d_modified, NULL));
  399.  
  400.          if ( dp->d_modified < expire )   /* Long in the tooth?      */
  401.          {                       /* Yes --> Move it on out           */
  402.             int not_processed = TRUE;
  403.                               /* Purge unless we archive it          */
  404.  
  405.             if ( archive != NULL )
  406.             {
  407.                printmsg( 4,"Archiving file %s from %s to %s",
  408.                         dp->d_name, directory , archive);
  409.  
  410.                if ( not_built )  /* First pass into directory?    */
  411.                {                 /* Yes --> Make sure it exists   */
  412.                   MKDIR( archive );
  413.                   not_built = FALSE;   /* Only build it once      */
  414.                }
  415.  
  416.                mkfilename( fname, archive, dp->d_name);
  417.                not_processed = rename( dp->d_name, fname );
  418.  
  419.                if ( not_processed )
  420.                {
  421.                   printerr( fname );
  422.                   printmsg(0,"Rename %s to %s failed, purging file.",
  423.                            dp->d_name, fname);
  424.                }
  425.                else {
  426.                   articles_archived++;
  427.                   bytes_archived += dp->d_size;
  428.                }
  429.             } /* if ( archive != NULL ) */
  430.  
  431.             if ( not_processed )
  432.             {
  433.                printmsg( 4,"Purging file %s from %s", dp->d_name, directory );
  434.                unlink( dp->d_name );
  435.                articles_purged++;
  436.                bytes_purged += dp->d_size;
  437.             } /* if ( not_processed ) */
  438.  
  439.          } /* if ( dp->d_modified < expire ) */
  440.  
  441. /*--------------------------------------------------------------------*/
  442. /*    If the article is valid and still in the main news              */
  443. /*    directory, determine if it is the lowest article left           */
  444. /*--------------------------------------------------------------------*/
  445.  
  446.          else {
  447.             long article = 0;
  448.             char *digit = dp->d_name;
  449.  
  450.             while( *digit )
  451.                article = article * 10 + (*digit++ - '0');
  452.  
  453.             low = min( article, low );
  454.  
  455.             bytes_kept += dp->d_size;
  456.             articles_kept ++;
  457.  
  458.          } /* else if ( archive != NULL ) */
  459.       } /* if ( numeric( dp->d_name ) */
  460.  
  461.    } /* while */
  462.  
  463. /*--------------------------------------------------------------------*/
  464. /*            Update lowest article available to the users            */
  465. /*--------------------------------------------------------------------*/
  466.  
  467.    if ( low == LONG_MAX )
  468.        cur_grp->grp_low = cur_grp->grp_high;
  469.    else
  470.        cur_grp->grp_low = low;
  471.  
  472. /*--------------------------------------------------------------------*/
  473. /*           Close up the directory and report what we did            */
  474. /*--------------------------------------------------------------------*/
  475.  
  476.    closedir(dirp);
  477.  
  478.    if ( articles_archived )
  479.       printmsg(2,"%s: Purged %d articles (%ld bytes),"
  480.                     " archived %d articles (%ld bytes),"
  481.                     " left alone %d articles (%ld bytes).",
  482.                   cur_grp->grp_name,
  483.                   articles_purged, bytes_purged,
  484.                   articles_archived, bytes_archived,
  485.                   articles_kept, bytes_kept );
  486.    else if ( articles_purged )
  487.       printmsg(2,"%s: Purged %d articles (%ld bytes),"
  488.                     " left alone %d articles (%ld bytes).",
  489.                   cur_grp->grp_name,
  490.                   articles_purged, bytes_purged,
  491.                   articles_kept, bytes_kept );
  492.    else if ( articles_kept )
  493.       printmsg(2,"%s: Left alone %d articles (%ld bytes).",
  494.                   cur_grp->grp_name,
  495.                   articles_kept, bytes_kept );
  496.  
  497.    total_articles_archived += articles_archived;
  498.    total_articles_kept     += articles_kept;
  499.    total_articles_purged   += articles_purged;
  500.    total_bytes_archived    += bytes_archived;
  501.    total_bytes_kept        += bytes_kept;
  502.    total_bytes_purged      += bytes_purged;
  503.  
  504. } /* ExpireDirectory */
  505.  
  506. /*--------------------------------------------------------------------*/
  507. /*    n u m e r i c                                                   */
  508. /*                                                                    */
  509. /*    Examines string, returns true if numeric with period            */
  510. /*--------------------------------------------------------------------*/
  511.  
  512.  static boolean numeric( char *start)
  513.  {
  514.    char *number = start;
  515.  
  516.    while (*number != '\0')
  517.    {
  518.       if (!isdigit(*number) && (*number != '.'))
  519.          return FALSE;
  520.  
  521.       number++;
  522.    }
  523.  
  524.    return TRUE;
  525.  } /* numeric */
  526.  
  527. /*--------------------------------------------------------------------*/
  528. /*    u s a g e                                                       */
  529. /*                                                                    */
  530. /*    Print usage of program                                          */
  531. /*--------------------------------------------------------------------*/
  532.  
  533. static void usage( void )
  534. {
  535.    printf( "Usage:   expire [-edays] [-adays] [-ngroup]\n");
  536.    exit(1);
  537. } /* usage */
  538.